<?php

declare(strict_types=1);

namespace App\Robot\Service;

use App\CustHub\Constants\CrowSendingConstants;
use App\CustHub\Constants\MsgTypeConstants;
use App\CustHub\Constants\RobotLoginStatusConstants;
use App\CustHub\Constants\SendConfigConstants;
use App\CustHub\Constants\SendRecordStatusConstants;
use App\CustHub\Constants\SmartPushSchemeStatusConstants;
use App\CustHub\Constants\SmartPushSchemeSubStatusConstants;
use App\CustHub\Constants\SmartPushSchemeTaskStatusConstants;
use App\CustHub\Constants\SmartPushSchemeTypeConstants;
use App\CustHub\Dto\AddMsgTemplateDto;
use App\CustHub\Mapper\ChRobotMapper;
use App\CustHub\Mapper\ChSendRecordMapper;
use App\CustHub\Mapper\ChSmartPushSchemeMapper;
use App\CustHub\Model\ChCrowdSending;
use App\CustHub\Model\ChCrowdSendingSubTask;
use App\CustHub\Model\ChSmartPushScheme;
use App\CustHub\Model\ChSmartPushSchemeSubTask;
use App\CustHub\Model\ChSmartPushSchemeTargetTask;
use App\CustHub\Model\ChSmartPushSchemeTask;
use App\CustHub\Model\ChSopSendTask;
use App\CustHub\Model\ChSopSendTaskMain;
use App\CustHub\Service\ChRoomKeywordService;
use App\Robot\Dto\RobotMsgDto;
use Carbon\Carbon;
use Hyperf\DbConnection\Db;
use Psr\Log\LoggerInterface;
use function Hyperf\Coroutine\co;

class SendRecordMessageHandlerService
{
    private ChSendRecordMapper $sendRecordMapper;
    private ChRobotMapper $robotMapper;
    private LoggerInterface $logger;

    public function __construct(
        ChSendRecordMapper $sendRecordMapper,
        ChRobotMapper      $robotMapper,
        LoggerInterface    $logger
    )
    {
        $this->sendRecordMapper = $sendRecordMapper;
        $this->robotMapper = $robotMapper;
        $this->logger = $logger;
    }

    /**
     * 处理消息发送逻辑
     */
    public function handle(array $data): void
    {
        $this->logInfo('消息发送处理中...', $data);
        $recordId = $data['record_id'];

        try {
            $recordInfo = $this->sendRecordMapper->findById($recordId);
            if (empty($recordInfo) || !$this->canSend($recordInfo)) {
                return;
            }
            //最后一条消息
            $isLastMsg = $data['is_last_msg'];
            //最后一个发送对象 变更任务状态
            $isLastSendItem = $recordInfo['is_last_send_item'] == 1;
            //最后一个子任务
            $isLastSubTask = $data['is_last_sub_task'] ?? true;

            $robotInfo = $this->robotMapper->findById($recordInfo->robot_id);
            $robotIsOnLine = $this->isRobotOnline($robotInfo, $recordId);
            if (!$robotIsOnLine) {
                $this->updateRecordStatusIfLastMsg($recordInfo, $recordId, 0, $isLastMsg, $isLastSendItem, $isLastSubTask,'机器人离线发送失败');
                return;
            }

            // 异步发送消息
            co(function () use ($recordInfo, $robotInfo, $recordId, $data, $isLastMsg, $isLastSendItem, $isLastSubTask) {
                $sentRes = $this->sendMessageAsync($recordInfo, $robotInfo, $data);
                $this->logger->info('异步发送消息结果:'.json_encode($sentRes));
                $sentCount = $sentRes['send_count'];
                $this->updateRecordStatusIfLastMsg($recordInfo, $recordId, $sentCount, $isLastMsg, $isLastSendItem, $isLastSubTask,$sentRes['errorMessage']);
                $this->sendRecordMapper->clearCache($recordId);
            });
        } catch (\Throwable $e) {
            stdout_log()->info('发送异常'.$e->getMessage());
            $this->handleException($e, $recordId);
        }
    }


    /**
     * 检查是否允许发送
     * @param $recordInfo
     * @return bool
     */
    private function canSend($recordInfo): bool
    {
        return in_array($recordInfo->status, SendRecordStatusConstants::getAllowSendStatus())
            && $recordInfo['start_time'] <= time();
    }

    /**
     * 检查机器人是否在线
     * @param $robotInfo
     * @param int $recordId
     * @return bool
     */
    private function isRobotOnline($robotInfo, int $recordId): bool
    {
        if ($robotInfo->login_status == RobotLoginStatusConstants::OFFLINE) {
            $this->sendRecordMapper->update($recordId, [
                'status' => SendRecordStatusConstants::FAILURE,
                'failure_reason' => '机器人离线'
            ]);
            return false;
        }
        return true;
    }

    /**
     * 异步发送消息
     * @param $recordInfo
     * @param $robotInfo
     * @param $data
     * @return array
     */
    private function sendMessageAsync($recordInfo, $robotInfo, $data)
    {
        $msgData = new RobotMsgDto();
        $msgData->setMsgType($data['msg_type'])
            ->setContent($data['content'])
            ->setToId($recordInfo['to_id'])
            ->setServerId($robotInfo['server_id'])
            ->setUuid($robotInfo['uuid'])
            ->setFilename($data['filename'] ?? '')
            ->setRecordId($recordInfo->id);

        //消息发送服务
        $result = make(\App\Robot\Service\RobotMessageService::class, [$msgData])->sendMessage();
        if ($result['status']) {
            // 消息发送成功，更新发送计数
            $this->sendRecordMapper->model::query()->where('id', $recordInfo->id)->increment('msg_sent_count');
            return ['send_count'=>1,'errorMessage'=>''];
        }
        return ['send_count'=>0,'errorMessage'=>$result['errorMessage']];
    }

    /**
     * 最后一条消息发送成功后更新状态
     * @param $recordInfo
     * @param int $recordId
     * @param int $sentCount
     * @param bool $isLastMsg
     * @return void
     */
    private function updateRecordStatusIfLastMsg($recordInfo, int $recordId, int $sentCount, bool $isLastMsg, bool $isLastSendItem, bool $isLastSubTask,$failMessage=''): void
    {
        if ($isLastMsg) {
            $successCount = $recordInfo['msg_sent_count'] + $sentCount;
            $isCompleted = false;
            $updateData = ['end_time' => time()];
            if ($successCount > 0) {
                $isCompleted = true;
                $updateData['status'] = SendRecordStatusConstants::SUCCESS;
            } else {
                $updateData['status'] = SendRecordStatusConstants::FAILURE;
                $updateData['failure_reason'] = $failMessage;
            }
            $this->sendRecordMapper->update($recordId, $updateData);
            $this->updateBusinessCount($recordInfo['type'], $recordInfo['task_id'],$recordInfo['sub_task_id'], $updateData['status'],$isLastSendItem,$isLastSubTask);
            $this->handleOtherEvents($recordInfo, $isCompleted, $isLastSendItem, $isLastSubTask);
        }
    }

    /**
     * 处理其他事件
     * @param $recordInfo
     * @param $isCompleted
     * @param bool $isLastSendItem
     * @param bool $isLastSubTask
     * @return void
     */
    private function handleOtherEvents($recordInfo, $isCompleted, bool $isLastSendItem, bool $isLastSubTask): void
    {
        $taskId = $recordInfo['task_id'];
        $subTaskId = $recordInfo['sub_task_id'];
        $type = $recordInfo['type'];
        switch ($type) {
            case SendConfigConstants::NEW_CUSTOMER:
                //新客户运营
                if($isCompleted){
                    $sendContent = $recordInfo['content'];
                    $sendContent = array_filter($sendContent,function ($item){
                        return $item['msg_type'] == MsgTypeConstants::TEXT;
                    });
                    stdout_log()->info('新客户运营发送文本需要触发下关键词拉群'.json_encode($sendContent,JSON_UNESCAPED_UNICODE));
                    if(!empty($sendContent)){
                        foreach ($sendContent as $item){
                            $robotInfo = $this->robotMapper->findById($recordInfo['robot_id']);
                            container()->get(ChRoomKeywordService::class)->getMeetTheConditionScheme([
                                'robot_user_id' => $robotInfo->user_id,
                                'user_id' => $recordInfo['to_id'],
                                'content' => $item['content'],
                                'is_robot' => 1,
                                'robotInfo' => $robotInfo->toArray(),
                            ]);
                        }
                    }
                }
                break;
            case SendConfigConstants::SMART_PUSH:
                $scheme = ChSmartPushScheme::query()
                    ->select(['id','uid','main_uid','push_type','push_tgt_switch','push_tgt_cfg'])
                    ->where('id', $taskId)
                    ->first();
                if(!empty($scheme)){
                    if($scheme->push_tgt_switch){
                        $push_tgt_cfg = $scheme->push_tgt_cfg;
                        $unit = $push_tgt_cfg['unit'];
                        $val = $push_tgt_cfg['val'];
                        if($unit == 0){
                            $beginTime = Carbon::now()->addDays($val)->timestamp;
                        }elseif($unit == 1){
                            $beginTime = Carbon::now()->addHours($val)->timestamp;
                        }else{
                            $beginTime = Carbon::now()->addMinutes($val)->timestamp;
                        }

                        //开启推送目标
                        $targetTaskData = [
                            'uid' => $scheme->uid,
                            'main_uid' => $scheme->main_uid,
                            'scheme_id' => $scheme->id,
                            'robot_id' => $recordInfo['robot_id'],
                            'user_id' => $recordInfo['to_id'],
                            'trigger_date' => Carbon::now()->toDateString(),//触发日期
                            'begin_time' => $beginTime,
                            'push_tgt_cfg' => $push_tgt_cfg,
                        ];
                        ChSmartPushSchemeTargetTask::create($targetTaskData);
                    }

                    if(!empty($subTaskId)){
                        //更新发送对象数量
                        ChSmartPushSchemeSubTask::query()
                            ->where('id',$subTaskId)
                            ->increment('completed_count');
                    }

                    //更新方案用户发送进度
                    if($isCompleted){
                        //触达数量
                        ChSmartPushScheme::query()
                            ->where('id', $taskId)
                            ->increment('reach_count');
                    }

                    if ($isLastSendItem) {
                        if(!empty($subTaskId)){
                            $subSchemeInfo = ChSmartPushSchemeSubTask::query()
                                ->with(['scheme'=>function ($query) {
                                    $query->select(['id','push_type']);
                                }])
                                ->where('id', $subTaskId)
                                ->first();

                            $subUpdate['status'] = SmartPushSchemeStatusConstants::COMPLETED;
                            ChSmartPushSchemeSubTask::query()
                                ->where('id', $subTaskId)
                                ->update($subUpdate);
                        }

                        if ($isLastSubTask) {
                            $update['is_running'] = 0;
                            if ($scheme->push_type == SmartPushSchemeTypeConstants::TIMING_SINGLE) {
                                $update['status'] = SmartPushSchemeStatusConstants::COMPLETED;
                            }

                            if($scheme->push_type == SmartPushSchemeTypeConstants::TIMING_REPEAT){
                                ChSmartPushSchemeTask::query()->where('id',$subSchemeInfo->task_id)->update([
                                    'status' =>  SmartPushSchemeTaskStatusConstants::COMPLETED
                                ]);
                            }
                            ChSmartPushScheme::query()
                                ->where('id', $taskId)
                                ->update($update);
                        }
                    }
                }
                break;
            default:
                break;
        }
    }


    /**
     * 更新各业务完成数量
     */
    private function updateBusinessCount(int $type, int $taskId,?int $subTaskId, int $sendStatus,bool $isLastSendItem, bool $isLastSubTask)
    {
        switch ($type) {
            case SendConfigConstants::HIGH_SENDING:
                //高级群发
//                logger()->info('群发发送完成后子任务id'.$subTaskId."任务id".$taskId."任务状态".$sendStatus);
//                DB::transaction(function () use ($taskId, $subTaskId, $sendStatus,$isLastSendItem,$isLastSubTask) {
//                    // 使用预加载减少查询次数
//                    $task = ChCrowdSending::find($taskId);
//                    $subTask = ChCrowdSendingSubTask::find($subTaskId);
//
//                    // 批量更新操作
//                    if ($sendStatus == SendRecordStatusConstants::SUCCESS) {
//                        $subTask->increment('success_total');
//                        $task->increment('success_total');
//                    } elseif ($sendStatus == SendRecordStatusConstants::FAILURE) {
//                        $subTask->increment('fail_total');
//                        $task->increment('fail_total');
//                    }
//
//                    // 使用条件更新避免不必要的查询
//                    if ($isLastSendItem) {
//                        $subTask->update(['status' => CrowSendingConstants::COMPLETE]);
//                    }
//                    if ($isLastSubTask) {
//                        $task->update(['status' => CrowSendingConstants::COMPLETE, 'end_time' => datetime(time())]);
//                    }
//                });
                break;
            case SendConfigConstants::SPEED_SENDING:
                //极速群发
                break;
            case SendConfigConstants::SOP:
                DB::transaction(function () use ($taskId, $subTaskId, $sendStatus,$isLastSendItem,$isLastSubTask) {
                    if ($sendStatus == SendRecordStatusConstants::FAILURE) {
                        ChSopSendTask::query()->where('id',$subTaskId)->update(['status'=>4]);
                    }
                });
                break;
        }
    }

    private function handleException(\Throwable $e, int $recordId): void
    {
        $this->logError('Task processing failed', ['record_id' => $recordId], $e);
        $this->sendRecordMapper->update($recordId, [
            'status' => SendRecordStatusConstants::FAILURE,
            'failure_reason' => '发送异常',
            'end_time' => time(),
        ]);
    }

    private function logInfo(string $message, array $context): void
    {
        $this->logger->info($message, array_merge($context, ['time' => time()]));
    }

    private function logError(string $message, array $context, \Throwable $e): void
    {
        $this->logger->error($message, array_merge($context, [
            'error' => $e->getMessage(),
            'time' => time(),
        ]));
    }
}
